from django.utils import simplejson
from django.http import HttpResponse
from django.contrib.gis.db.models import *
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
from django.contrib.gis.geos.collections import GeometryCollection
import models,re
import datetime
import settings

from django.db import connection
from django.core.exceptions import ValidationError

import os,subprocess,zipfile,simplejson
import logging
logging.basicConfig(
    level = logging.DEBUG,
    format = '%(asctime)s %(levelname)s %(message)s',
)

def float_or_null(operand):
    try:
        return float(operand)
    except ValueError:
        return None

def get_group_config(request):
    try:
        conf=models.group_attribute.objects.get(
            domain = re.sub(r"(/$|:8000|http://)","",request.META['HTTP_HOST'])
        )
        return conf
    except models.group_attribute.DoesNotExist:
        try:
            return models.group_attribute.objects.get(
            domain = re.sub(r"(/$|:8000|http://)","",settings.HOST)
            )
        except models.group_attribute.DoesNotExist:
            return None

def date_or_null(operand):
    try:
        return datetime.datetime.strptime(operand,"%Y-%M-%d")
    except ValueError:
        return None
        
def jsonResponse(dict):
    return HttpResponse(simplejson.dumps(dict))

def first_item(dict):
    for val in dict.values():return val

def file_extension(filename):
    pos = filename.rfind('.')
    if pos > -1:
        return filename[pos+1:]
    else:
        return None

def get_anon_user(group):
    logging.debug(group)
    logging.debug(group.name.replace("-","_"))
    return User.objects.get(username = group.name.replace("-","_"))


def render_to_geojson(query_set, model, geom_field=None, mimetype='text/plain', pretty_print=settings.DEBUG, exclude=[],
                      maxpoints=None, raw=False):
    """
    Shortcut to render a GeoJson FeatureCollection from a Django QuerySet.
    Currently computes a bbox and adds a crs member as a sr.org link
    """
    collection = {}

    # Find the geometry field
    # qs.query._geo_field()

    fields = model._meta.fields
    geo_fields = [f for f in fields if isinstance(f, GeometryCollectionField)]
    #attempt to assign geom_field that was passed in
    if geom_field:
        geo_fieldnames = [x.name for x in geo_fields]
        #try:
        geo_field = geo_fields[geo_fieldnames.index(geom_field)]
        #except:
        #    raise Exception('%s is not a valid geometry on this model' % geom_field)
    else:
        geo_field = geo_fields[0] # no support yet for multiple geometry fields

    #remove other geom fields from showing up in attributes
    if len(geo_fields) > 1:
        for gf in geo_fields:
            if gf.name not in exclude: exclude.append(gf.name)
        exclude.remove(geo_field.name)

    # Gather the projection information
    crs = {'type': "link"}
    crs_properties = {'href': 'http://spatialreference.org/ref/epsg/%s/' % geo_field.srid, 'type': 'proj4'}
    crs['properties'] = crs_properties
    collection['crs'] = crs

    # Build list of features
    features = []
    if query_set:
        for item in query_set:
            feat = {'type': 'Feature'}
            d = {}
            i = item.__dict__
            for k in i.keys():
                if type(k) == str and k[0] == '_':
                    continue
                elif type(i[k]) == datetime.date:
                    d[k] = str(i[k])
                else:
                    d[k] = i[k]

            g = getattr(item, geo_field.name)


            ## attributes.
            d = item.__dict__.copy()
            d.pop(geo_field.name)
            for field in exclude:
                d.pop(field)
#d.pop('_state')

            feat['properties'] = d

            if maxpoints and g and g.num_coords > maxpoints:
                g = g.envelope
                feat['properties']['envelope'] = True

            if g: feat['geometry'] = simplejson.loads(g.geojson)
            features.append(feat)
    else:
        pass #features.append({'type':'Feature','geometry': {},'properties':{}})

    # Label as FeatureCollection and add Features
    collection['type'] = "FeatureCollection"
    collection['features'] = features

    dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else str(obj)
    if raw:
        return simplejson.dumps(collection, default=dthandler)
    response = HttpResponse()
    if pretty_print:
        response.write('%s' % simplejson.dumps(collection, default=dthandler, indent=1))
    else:
        response.write('%s' % simplejson.dumps(collection, default=dthandler))
    response['Content-length'] = str(len(response.content))
    response['Content-Type'] = mimetype
    return response



# generic function that fetches all records from a
# specified table and converts them to json string
def django2python(all_records,fields=None,follow = []):

    if len(all_records) == 0:
        return {}

    if all_records[0] == None:
        return None

    response_dict={}

    if fields is None and len(all_records) > 0:
        fields = all_records[0].__dict__.keys()

    for record in all_records:
  
        record_dict = {}

        # compile the standard attributes of this object into a dict for JSON.
        for key in fields:
            if key[0:1] == '_': continue
            
            item = getattr(record,key)
            # convert anything that's not an int or a float to a string.
            if type(item) in [int,float]:
                record_dict[key] = item
            elif type(item) == GeometryCollection:
                record_dict[key] = render_to_geojson([record], models.UserUploadedShapes, 'geoms', raw=True)
            elif hasattr(item,'id'):
                record_dict[key] = id
            elif type(item) is list:
                for key in m:
                    if hasattr(record,key):
                        record_dict[key] = [item.id for item in getattr(record,key)]
                    else:
                        record_dict[key] = []
            #TODO: consider using javascript dates properly.
            #elif type(item) == datetime:
            #    record_dict[key] = "new Date (%s,%s,%s,%s,%s)" % ( item.year, item.month - 1, item.day, item.hour, item.minute)
            else:
                record_dict[key] = unicode(item)
        # resolve many-to-many relationships        
        for rel in follow:
            val = getattr(record,rel)
            if hasattr(val,'all'): #manytomany
              record_dict[rel] = [obj.id for obj in val.all()]
            elif not val:
              record_dict[rel] = None
            else:
              record_dict[rel] = django2python([val]).values()[0]
        # compile the foreign keys and many-to-many relationship attributes of this object into a list of IDs.
        response_dict[record_dict['id']] = record_dict

    return response_dict

def django2json(records, fields=None,follow=[]):
      return simplejson.dumps( django2python( records,fields,follow ) )

'''
Validates an SRS parameter passed in a request
'''
def _validate_srs(srs_str):
    #Verify SRS format
    import re
    p = re.compile('^[a-zA-Z]*:[0-9]*$')
    if not p.match(srs_str):
        return False
    return True


def Hex2RGB(hexstr):
    hexstr = hexstr.strip()
    if len(hexstr) == 0:
        return ''
    if hexstr[0] == '#':
        hexstr = hexstr[1:]
    if len(hexstr) != 6:
        return ''
    try:
        return str(int(hexstr[:2], 16)) + ' ' + str(int(hexstr[2:4], 16)) + ' ' + str(int(hexstr[4:], 16))
    except:
        return ''

def Color2OutlineColor(hexstr):
    hexstr = hexstr.strip()
    if len(hexstr) == 0:
        return ''
    if hexstr[0] == '#':
        hexstr = hexstr[1:]
    if len(hexstr) != 6:
        return ''
    try:
        r = int(hexstr[:2], 16) * 255
        g = int(hexstr[2:4], 16) *  255
        b = int(hexstr[4:], 16) * 255
        yiq = (r * 299 + g * 587 + b * 114) / 1000.0;
        if yiq >= 128:
            return '1 1 1'
        else:
            return '255 255 255'
    except:
        return ''

def generate_map_file(new_wms_layer=None):
    cursor = connection.cursor()
    cursor.execute("select table_name from information_schema.tables where table_name LIKE 'user_shape_%%'")
    table_names = cursor.fetchall()
    table_names = [t[0] for t in table_names]
    mapserverdir = os.path.join(settings.ROOT, 'mapserver')
    mapfile = open(os.path.join(mapserverdir, 'user_shapes.map'), 'w')
    wms_layers = list(models.wms_layer.objects.all())
    #if the new wms_layer is a new one, append it to the list.
    #otherwise replace it with the old one in the list.
    if new_wms_layer:
        new_layer = True
        for i in range(len(wms_layers)):
            if wms_layers[i].layers == new_wms_layer.layers:
                wms_layers[i] = new_wms_layer
                new_layer = False
                break
        if new_layer:
            wms_layers.append(new_wms_layer)

    for wms in wms_layers:
        layers = wms.layers
        table_name = 'user_shape_%s' % layers
        if table_name.lower() not in table_names:
            continue
        style = simplejson.loads(wms.style)
        COLORstr = Hex2RGB(style['COLOR'])
        OUTLINECOLORstr = Hex2RGB(style['OUTLINECOLOR'])
        if COLORstr:
            COLORstr = '''
                COLOR ''' + COLORstr
        if OUTLINECOLORstr:
            OUTLINECOLORstr = '''
                OUTLINECOLOR ''' + OUTLINECOLORstr

        has_label = wms.label_field_name  and wms.label_field_name != ""
        labelstyle = simplejson.loads(wms.label_style)
        LABELstr = ''
        LABELstylestr = ''
        if has_label:
            label_field_name = wms.label_field_name.strip()
            LABELstr = '''
            LABELITEM "''' + label_field_name + '''"
            LABELCACHE ON'''
            LABELstylestr = '''
                LABEL
                  TYPE truetype
                  SIZE ''' + labelstyle['SIZE'] + '''
                  FONT ''' + labelstyle['FONT'] + '''
                  POSITION cc
                  COLOR ''' + Hex2RGB(labelstyle['COLOR']) + '''
                  OUTLINECOLOR ''' + Color2OutlineColor(labelstyle['COLOR']) + '''
                  PARTIALS FALSE
                  FORCE FALSE
                END'''

        mapfile.write('''
        LAYER
            NAME "''' + layers + '''"
            STATUS OFF
            DATA "the_geom from ''' + table_name + ''' using unique gid using SRID=4326"
            CONNECTIONTYPE POSTGIS
            CONNECTION "user=ce_atlas dbname=ce_atlas host=localhost password=''' + settings.DATABASE_PASSWORD + '''"
            METADATA
                "wms_title" "''' + wms.title + '''"
            END
            TYPE ''' + wms.user_file_type + '''
            UNITS meters
            PROJECTION
                "init=EPSG:4326"
            END
            DUMP TRUE
            TRANSPARENCY 70
            TEMPLATE foo''' + LABELstr + '''
            CLASS
                NAME "''' + wms.title + '''"
                STYLE''' + COLORstr + OUTLINECOLORstr + '''
                  WIDTH ''' + style['WIDTH'] + '''
                END''' + LABELstylestr + '''
            END
        END
        ''')
    mapfile.close()



